package ar.edu.utn.frba.dds.opendesigners.aerolineas.oceanic;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

import com.oceanic.AsientoDTO;

import ar.edu.utn.frba.dds.opendesigners.ParametroBusqueda;
import ar.edu.utn.frba.dds.opendesigners.aerolineas.AerolineaAdapter;
import ar.edu.utn.frba.dds.opendesigners.excepciones.ExcepcionCompraAsiento;
import ar.edu.utn.frba.dds.opendesigners.excepciones.ExcepcionReservaAsiento;
import ar.edu.utn.frba.dds.opendesigners.fecha.Fecha;
import ar.edu.utn.frba.dds.opendesigners.formato.FormatoSimple;
import ar.edu.utn.frba.dds.opendesigners.reservas.Reservas;
import ar.edu.utn.frba.dds.opendesigners.resultados.VueloDirecto;
import ar.edu.utn.frba.dds.opendesigners.resultados.ResultadoBusqueda;
import ar.edu.utn.frba.dds.opendesigners.resultados.Asiento;

public class OceanicAdapter extends AerolineaAdapter{

	private InterfaceOceanic oceanic;
	private TipoBusqueda tipoDeBusqueda;
	
	//Para probar con el MOKE de Oceanic
	public OceanicAdapter(InterfaceOceanic aerolineaOceanic, Reservas reservasDeAterrizar){
		this.oceanic = aerolineaOceanic;
		this.tipoDeBusqueda = new TipoBusqueda(aerolineaOceanic);
		this.registroReservas = reservasDeAterrizar;
	}

	public void comprar(VueloDirecto asiento) {
		if(!( this.oceanic.comprarSiHayDisponibilidad(asiento.getDni(), asiento.getNumeroVuelo(), Integer.parseInt(asiento.getNumeroAsiento())) ))
			throw new ExcepcionCompraAsiento();
		this.registroReservas.quitarReserva(asiento);
		this.estadistica.agregarCompras(asiento);			
	}

	public OceanicAdapter getAerolinea() {
		return this;
	}

	@Override
	public BigDecimal getRecargo() {
		return new BigDecimal(0);
	}

	@Override
	public ResultadoBusqueda buscar(ParametroBusqueda parametroBusqueda) {
		Fecha fechaActual = new Fecha(Calendar.getInstance());
		Fecha fechaDeParametro =  new Fecha( new FormatoSimple("dd/MM/yyyy").crear(parametroBusqueda.getFecha()) );
		List<AsientoDTO> resultadoBusqueda = new ArrayList<AsientoDTO>();
		
		while( fechaActual.anteriorOIgual(fechaDeParametro) ){
		 resultadoBusqueda.addAll( this.tipoDeBusqueda.buscar(this.convertirFormatoCiudad(parametroBusqueda.getOrigen()),	this.convertirFormatoCiudad(parametroBusqueda.getDestino()),	fechaActual.stringFecha("dd/MM/yyyy")) );
		 fechaActual.diaSiguiente();
		}		
		
		return this.convertirBusquedaEn(this.filtrarBusquedaPorFecha(resultadoBusqueda, parametroBusqueda.getFecha()));
	}
	

	/**
	 * Dados los parametros listSearch y date retorna los asientos que estan en el rango de la fecha.
	 * Siempre debe de pasarse listSearch y date
	 * 
	 * @param busqueda
	 * 		Lista con asientos a filtrar
	 * @param fecha
	 * 		Fecha por la cual filtrar
	 * @return
	 * 		la lista de @see AstientoDTO que cumplen con el filtro
	 */
	private List<AsientoDTO> filtrarBusquedaPorFecha(List<AsientoDTO> busqueda, String fecha) {
		
		List<AsientoDTO> busquedaFiltrada = new ArrayList<AsientoDTO>();
		//Fecha para filtrar segun....
		Fecha fechaDeParametro = new Fecha( new FormatoSimple("dd/MM/yyyy").crear(fecha) );
		

		//Para cada asiento, 
		for (AsientoDTO asientoDTO : busqueda) {

			//Fechas de partida y de llegada
			Fecha fechaOrigen = new Fecha(new FormatoSimple("dd/MM/yyyy").crear(asientoDTO.getFechaDeSalida()));
			Fecha fechaDestino = new Fecha(new FormatoSimple("dd/MM/yyyy").crear(asientoDTO.getFechaDeLlegada()));
			
			if( fechaOrigen.anteriorOIgual(fechaDeParametro) && fechaDestino.posteriorOIgual(fechaDeParametro))
				busquedaFiltrada.add(asientoDTO);
		}
		return busquedaFiltrada;
		
	}
	/**
	 * Toma el parametro city y lo convierte segun el criterio de OCEANIC
	 * @param ciudad
	 * 		Representacion de la ciudad
	 * @return
	 * 		La representación de la ciudad transformada
	 */		
	private String convertirFormatoCiudad(String ciudad) {

		//Oceanic hace comparacion de referencia de objetos.
		//Esto lo recomiendan para optimización del compilador, pero a mi no me gusta nada!
		//Porque queda asqueroso el codigo y en algunos casos podria ser ilegible!
		String conversionCiudad = "";
		try {
			if(ciudad.equals("BS")) conversionCiudad = "_BS";
			if(ciudad.equals("LA")) conversionCiudad = "SLA";
			if(ciudad.equals("NY")) conversionCiudad = "_NY";			
		} catch (NullPointerException e) {
			conversionCiudad = "";
		}
		return conversionCiudad;
	}
	
	/**
	 * Dada la lista de asientos seats, la convierte en el tipo SearchResponse
	 * @param asientos
	 * 		Lista de Asientos 
	 * @return
	 * 		el @see SearchResponse representa la lista transformada @see seats
	 */
	private ResultadoBusqueda convertirBusquedaEn(List<AsientoDTO> asientos){
		ResultadoBusqueda response = new ResultadoBusqueda();
		for (AsientoDTO asientoDTO : asientos) {
			VueloDirecto item = (new ConversorAsientosOceanic()).convertirAsiento(asientoDTO, this.getAerolinea());  			
			 response.agregarItem((Asiento) item);
		}
		return response;
	}
	
	@Override
	public boolean reserva(VueloDirecto asientos){
		if(!this.oceanic.reservar(asientos.getDni(), asientos.getNumeroVuelo(), Integer.parseInt(asientos.getNumeroAsiento()))){
			throw new ExcepcionReservaAsiento();
		}
		return true;
	}
}
